﻿/**
 * SlotDuino
 * 
 * Copyright (c) 2011/2012 Thiago Hummel Moreira, Ricardo Mizuuti, Rafael Mufato, Bruno Sakai, Andre Turina
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Windows;
using SlotDuino.DAL;

namespace SlotDuino.Util
{
    public static class Authentication
    {
        public static bool NeedFirstRun()
        {
            using (EntityContainer context = new EntityContainer())
            {
                //Check for at least one administrator
                var loginQuery = from p in context.People.OfType<Operator>() where p.IsAdministrator.Equals(true) select p;

                //If there is no one, need to pass the first run
                return (0 == loginQuery.Count());
            }
        }

        public static bool DoLogin(string login, string password, bool hashed = false)
        {
            //Produces the hashed version of the informed password
            string hashedPwd = (hashed ? password : CalculateSHA1(password));

            try
            {
                using (EntityContainer context = new EntityContainer())
                {
                    //Search the operators list for specified login
                    var loginQuery = from p in context.People.OfType<Operator>() where p.Login.Equals(login) select p;

                    //If we find one operator and the passwords match
                    if (1 != loginQuery.Count())
                    {
                        throw new Exception("Wrong username.");
                    }

                    //Get the operator with the specified login
                    Operator user = loginQuery.First();
                    if (!user.Password.Equals(hashedPwd))
                    {
                        throw new Exception("Wrong Password.");
                    }

                    //Set the app logged user
                    App slotduino = (App)Application.Current;
                    slotduino.LoggedUser = user;
                }

                //Login info is valid
                return true;
            }
            catch
            {
                //Login info is invalid
                return false;
            }
        }

        public static bool DoLogin(Operator user)
        {
            return DoLogin(user.Login, user.Password, true);
        }

        public static string CalculateSHA1(string data)
        {
            var sha = new SHA1CryptoServiceProvider();
            return BitConverter.ToString(sha.ComputeHash(Encoding.UTF8.GetBytes(data))).Replace("-", "").ToLower();
        }

        public static Operator CreateDefaultAdminUser(string password)
        {
            Operator user;
            using (EntityContainer context = new EntityContainer())
            {
                user = new Operator();
                user.Name = "Administrador";
                user.Login = "admin";
                user.IsAdministrator = true;
                user.Password = CalculateSHA1(password);
                
                context.AddToPeople(user);
                context.SaveChanges();
            }

            return user;
        }

        public static Operator GetLoggedUser()
        {
            return ((App)Application.Current).LoggedUser;
        }
    }
}
